package com.starlinkdt.common.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

/**
 * JSON工具类
 *
 * @author system
 */
public final class JSONUtils {

    private static final String PATTERN = "yyyy-MM-dd HH:mm:ss";
    private static final ObjectMapper JSON_MAPPER = new ObjectMapper();

    private static final JavaType[] DEFAULT_BLANK_JAVA_TYPE = new JavaType[0];

    static {
        // 关闭空对象序列化失败
        JSON_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // 忽略未知字段
        JSON_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 解析时允许识别JSON里的注释
        JSON_MAPPER.configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature(), true);
        // 解析时允许以0开头的数字
        JSON_MAPPER.configure(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS.mappedFeature(), true);
        // 解析时允许包含制控制字符(/n、/t等)
        JSON_MAPPER.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
        //解析时保持时区为东八区
        JSON_MAPPER.setTimeZone(TimeZone.getDefault());
    }

    private JSONUtils() {
    }

    /**
     * 对象转为JSON字符串
     *
     * @param object 对象
     * @return JSON字符串
     */
    public static String toJSONString(Object object) {
        if (object == null) {
            return null;
        }
        try {
            return JSON_MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException ignore) {
            return null;
        }
    }

    /**
     * JSON字符串解析为对象
     *
     * @param json  JSON字符串
     * @param clazz 对象类型
     * @param <T>   对象类型
     * @return 解析后的对象
     */
    public static <T> T parseObject(String json, Class<T> clazz) {
        if (json == null) {
            return null;
        }
        try {
            return JSON_MAPPER.readValue(json, clazz);
        } catch (JsonProcessingException ignore) {
            return null;
        }
    }

    /**
     * JSON字符串解析为对象
     *
     * @param json     JSON字符串
     * @param javaType 对象类型
     * @param <T>      返回对象类型
     * @return 解析后的对象
     */
    public static <T> T parseObject(String json, JavaType javaType) {
        if (json == null) {
            return null;
        }
        try {
            return JSON_MAPPER.readValue(json, javaType);
        } catch (JsonProcessingException ignore) {
            return null;
        }
    }

    /**
     * JSON字符串解析为对象数组
     *
     * @param json  JSON字符串
     * @param clazz 对象类型
     * @param <T>   对象类型
     * @return 解析后的对象数组
     */
    public static <T> List<T> parseList(String json, Class<T> clazz) {
        if (json == null) {
            return Collections.emptyList();
        }
        try {
            return JSON_MAPPER.readValue(json, constructParametricType(List.class, clazz));
        } catch (JsonProcessingException ignore) {
            return Collections.emptyList();
        }
    }

    /**
     * JSON字符串解析为对象MAP
     *
     * @param json JSON字符串
     * @param clazzK 对象类型
     * @param clazzV 对象类型
     * @param <K>   对象类型
     * @param <V>   对象类型
     * @return 解析后的对象
     */
    public static <K, V> Map<K, V> parseMap(String json, Class<K> clazzK, Class<V> clazzV) {
        if (json == null) {
            return Collections.emptyMap();
        }
        try {
            return JSON_MAPPER.readValue(json, constructParametricType(Map.class, clazzK, clazzV));
        } catch (JsonProcessingException ignore) {
            return Collections.emptyMap();
        }
    }

    /**
     * 判断字符串是否为json
     *
     * @param json
     * @return boolean
     */
    public static boolean isValidJSON(String json) {
        if (json == null) {
            return false;
        }
        try {
            JsonNode jsonNode = JSON_MAPPER.readTree(json);
            return true;
        } catch (JsonProcessingException ignore) {
            return false;
        }
    }

    /**
     * 创建解析类型
     *
     * @param parametrized     外层参数类型
     * @param parameterClasses 内层参数类型
     * @return 解析类型
     */
    public static JavaType constructParametricType(Class<?> parametrized, Class<?>... parameterClasses) {
        return JSON_MAPPER.getTypeFactory().constructParametricType(parametrized, parameterClasses);
    }

    /**
     * 创建解析类型
     *
     * @param rawType        外层参数类型
     * @param parameterTypes 内层参数类型
     * @return 解析类型
     */
    public static JavaType constructParametricType(Class<?> rawType, JavaType... parameterTypes) {
        return JSON_MAPPER.getTypeFactory().constructParametricType(rawType, parameterTypes);
    }

    /**
     * 类转为JavaType
     *
     * @param rawType 类型
     * @return JavaType对象
     */
    public static JavaType constructToJavaType(Class<?> rawType) {
        return JSON_MAPPER.getTypeFactory().constructParametricType(rawType, DEFAULT_BLANK_JAVA_TYPE);
    }

    /**
     * 获取ObjectMapper，供特殊处理
     *
     * @return ObjectMapper对象
     */
    public static ObjectMapper getObjectMapper() {
        return JSON_MAPPER;
    }
}
